package com.niiwoo.civet.account.service.local.creditorTransfer;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.OrderSuccessAccounting;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.bill.AddBillDetailDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.request.CreditorTransferSuccessAccountingRequestDTO;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.account.service.local.trade.OrderSuccessAccountingLocalService;
import com.niiwoo.civet.base.enums.BorrowProjectTypeEnum;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.trade.constant.PlatformConstant;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 债权转让Facade
 * Created by xiaoyingping on 2018/7/12.
 */
@Service
@Slf4j
public class CreditorTransferFacade {

    @Autowired
    private OrderSuccessAccountingLocalService orderSuccessAccountingLocalService;
    @Autowired
    private BillFacade billFacade;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;


    /**
     * 债转成功记账
     *
     * @param requestDTO
     * @return
     */
    @Transactional
    public Long transferSuccessAccounting(CreditorTransferSuccessAccountingRequestDTO requestDTO) {
        log.info("transferSuccessAccounting start:{}", JSON.toJSON(requestDTO));
        //新增债转记账成功记录
        OrderSuccessAccounting orderSuccessAccounting = orderSuccessAccountingLocalService.queryOrderSuccessAccountingByOrderIdAndOrderType(requestDTO.getSaleDetailId(), OrderTypeEnum.CREDITOR_TRANSFER);
        if(Objects.nonNull(orderSuccessAccounting)){
            log.info("债转记账成功记录已存在，直接返回");
            return orderSuccessAccounting.getId();
        }
        Long orderSuccessAccountingId = orderSuccessAccountingLocalService.insertOrderSuccessAccounting(requestDTO.getSaleDetailId(), OrderTypeEnum.CREDITOR_TRANSFER);

        //债权受让人的投资账单修改为"成功"
        billFacade.successBillByOrderId(requestDTO.getInvestUserId(), requestDTO.getInvestOrderId().toString(), OrderTypeEnum.INVEST);

        //计算转让金额中的本金和利息
        BigDecimal transferCorpusAmount = requestDTO.getDueInCorpusAmount();//转让本金
        BigDecimal transferInterestAmount = requestDTO.getTransferAmount().subtract(requestDTO.getDueInCorpusAmount());//转让利息 = 转让金额 - 待收本金
        if(transferInterestAmount.compareTo(BigDecimal.ZERO) < 0){
            transferCorpusAmount = requestDTO.getTransferAmount();//利息为0，并且本金等于转让金额（也有折扣）
            transferInterestAmount = BigDecimal.ZERO;
        }

        //债权转让人记账
        AccountBase saleUserAccount = accountService.loadNiiwooAccount(requestDTO.getSaleUserId(), UserRoleEnum.INVESTOR);
        AccountBase investUserAccount = accountService.loadNiiwooAccount(requestDTO.getInvestUserId(), UserRoleEnum.INVESTOR);
        AccountBase platformAccount = accountService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);

        List billDetailDTOList = new ArrayList();
        AddBillDetailDTO billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(transferCorpusAmount);
        billDetailDTO.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_TRANSFER_CORPUS);//出让价格中的本金部分
        billDetailDTO.setRelationAccountId(investUserAccount.getId());
        billDetailDTO.setRelationUserId(investUserAccount.getUserId());
        billDetailDTOList.add(billDetailDTO);

        billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(transferInterestAmount);
        billDetailDTO.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_TRANSFER_INTEREST);//出让价格中的利息部分
        billDetailDTO.setRelationAccountId(investUserAccount.getId());
        billDetailDTO.setRelationUserId(investUserAccount.getUserId());
        billDetailDTOList.add(billDetailDTO);

        billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(requestDTO.getTransferManagementFee());
        billDetailDTO.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_TRANSFER_CREDITOR_OUT_SERVICE_FEE);//债转服务费
        billDetailDTO.setRelationAccountId(platformAccount.getId());
        billDetailDTO.setRelationUserId(platformAccount.getUserId());
        billDetailDTOList.add(billDetailDTO);

        AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
        billDTO.setAccountId(saleUserAccount.getId());
        billDTO.setAmount(requestDTO.getTransferAmount().subtract(requestDTO.getTransferManagementFee()));//转让金额-转让服务费
        billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
        billDTO.setOrderId(requestDTO.getSaleDetailId());
        billDTO.setOrderType(OrderTypeEnum.CREDITOR_TRANSFER);
        billDTO.setRequestNo(requestDTO.getRequestNo());
        billDTO.setStatus(BillStatusEnum.SUCCESS);
        billDTO.setChannelCode(ChannelCodeEnum.APP);
        billDTO.setProjectId(requestDTO.getSaleDetailId());
        billDTO.setProjectType(BorrowProjectTypeEnum.TRANSFER_OF_CREDIT);
        billDTO.setProjectTitle(requestDTO.getSaleDetailTitle());
        billDTO.setAddBillDetailDTOList(billDetailDTOList);
        billFacade.addBillAndChangeBalance(billDTO);

        //平台记帐
        billDetailDTOList = new ArrayList();
        billDetailDTO = new AddBillDetailDTO();
        billDetailDTO.setAmount(requestDTO.getTransferManagementFee());
        billDetailDTO.setBillSecondSubjectEnum(BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_TRANSFER_CREDITOR);
        billDetailDTO.setRelationAccountId(saleUserAccount.getId());
        billDetailDTO.setRelationUserId(saleUserAccount.getUserId());
        billDetailDTOList.add(billDetailDTO);

        billDTO = new AddBillAndChangeBalanceDTO();
        AccountBase plateformAccount = accountService.loadNiiwooAccount(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME);
        billDTO.setAccountId(plateformAccount.getId());
        billDTO.setAmount(requestDTO.getTransferManagementFee());
        billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
        billDTO.setOrderId(requestDTO.getSaleDetailId());
        billDTO.setOrderType(OrderTypeEnum.CREDITOR_TRANSFER);
        billDTO.setRequestNo(requestDTO.getRequestNo());
        billDTO.setStatus(BillStatusEnum.SUCCESS);
        billDTO.setChannelCode(ChannelCodeEnum.APP);
        billDTO.setProjectId(requestDTO.getSaleDetailId());
        billDTO.setProjectType(BorrowProjectTypeEnum.TRANSFER_OF_CREDIT);
        billDTO.setProjectTitle(requestDTO.getSaleDetailTitle());
        billDTO.setAddBillDetailDTOList(billDetailDTOList);
        billFacade.addBillAndChangeBalance(billDTO);

        /**
         * 出让人财富数据变更
         */
        //出让人: 减少待收本金
        List<MoneyTotalDTO> moneyTotalDTOList = new ArrayList<>();
        MoneyTotalDTO moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(saleUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.DUE_IN_CORPUS);
        moneyTotalDTO.setAmount(requestDTO.getDueInCorpusAmount().negate());
        moneyTotalDTOList.add(moneyTotalDTO);
        //出让人：减少待收利息
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(saleUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.DUE_IN_INTEREST);
        moneyTotalDTO.setAmount(requestDTO.getDueInInterestAmount().negate());
        moneyTotalDTOList.add(moneyTotalDTO);
        //出让人：累计债权出让手续费
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(saleUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.CREDITOR_SALE_FEE);
        moneyTotalDTO.setAmount(requestDTO.getTransferManagementFee());
        moneyTotalDTOList.add(moneyTotalDTO);
        //出让人: 累计投资收益
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(saleUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.INVEST_INCOME);
        moneyTotalDTO.setAmount(requestDTO.getTransferAmount().subtract(requestDTO.getDueInCorpusAmount()));
        moneyTotalDTO.setAmount(moneyTotalDTO.getAmount().compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : moneyTotalDTO.getAmount());
        moneyTotalDTOList.add(moneyTotalDTO);

        moneyTotalLocalService.moneyTotal(moneyTotalDTOList);

        /**
         * 受让人财富数据变更
         */
        //受让人：累计投资金额
        moneyTotalDTOList = new ArrayList<>();
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(investUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.INVEST_TOTAL);
        moneyTotalDTO.setAmount(requestDTO.getTransferAmount());
        moneyTotalDTOList.add(moneyTotalDTO);
        //受让人：释放投资冻结金额
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(investUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.INVEST_FREEZE);
        moneyTotalDTO.setAmount(requestDTO.getTransferAmount().negate());
        moneyTotalDTOList.add(moneyTotalDTO);
        //受让人: 累计待收本金
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(investUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.DUE_IN_CORPUS);
        moneyTotalDTO.setAmount(requestDTO.getDueInCorpusAmount());
        moneyTotalDTOList.add(moneyTotalDTO);
        //受让人：累计待收利息
        moneyTotalDTO = new MoneyTotalDTO();
        moneyTotalDTO.setAccountId(investUserAccount.getId());
        moneyTotalDTO.setAmountType(AccountAmountTypeEnum.DUE_IN_INTEREST);
        moneyTotalDTO.setAmount(requestDTO.getDueInInterestAmount());
        moneyTotalDTOList.add(moneyTotalDTO);

        moneyTotalLocalService.moneyTotal(moneyTotalDTOList);

        log.info("transferSuccessAccounting end:{}", JSON.toJSONString(requestDTO));
        return orderSuccessAccountingId;
    }


}
